<!-- 发展历程,该功能进入的时候需要将所有的地铁路线都清除，离开的时候再添加回来，使用该功能的时候无法使用图层管理控件 -->
<template>
    <div>
        <div id="subLine-controller">
            <div class="item-wrapper">
                <div class="item" v-for="item in subLineData" @click.stop="handleItemClick(item)">
                    <div class="box" :style="{ borderColor: item.color, backgroundColor: item.color }"></div>
                    <span :style="{ color: '#34c5cf' }">{{ item.name.slice(-3) }}</span>
                </div>
            </div>
        </div>
        <div class="active-panel">
            <div class="header">
                <strong>发展历程</strong>
                <div class="controler">
                    <i class="iconfont metro-pause" @click="pause"></i>
                    <i class="iconfont metro-play" @click="play"></i>
                    <i class="iconfont metro-icon-replay-copy" @click="replay"></i>
                </div>
            </div>
            <div class="content">
                <a-slider style="width: 500px" v-if="resPaths.length!==0" v-model:value="currentTime" :marks="marks" :step="0.5" :min="0" :max="max"
                    :disabled="true">
                </a-slider>
            </div>
            <div class="message" v-if="message.length">
                {{ message }}
            </div>
        </div>
    </div>
</template>

<script setup>
import { ref,onMounted,onBeforeUnmount,watch } from 'vue'
import { useLineData } from '../store'

const lineDataStore = useLineData()
const subLineData = ref(null)//所有线路信息
import { polygon, centroid } from 'turf'
import { flattenPositions } from '@/cesiumTools/core'//将[{lng,lat}]--->[lng,lat,lng,lat]
import _, { create } from 'lodash'
import { renderAll, removeByCacheData } from '@/cesiumTools/effectController'
import { line_history } from '@/store/staticData'//发展历程mock
import { flyToDefaultView } from "@/cesiumTools/sceneManager";


const currentTime = ref(0);//当前时间进度
const marks = ref({});//播放控件信息
const max = ref(100);//
const message = ref("");//重大事件
let viewer
// 地铁线的路径数组
let curPaths = [];//动态坐标的初始值
let resPaths = [];//路径数据(所有站点的经纬度)
let isAnimate = false//控制动画是否播放

onMounted(()=>{
    viewer = lineDataStore.viewer
    subLineData.value = lineDataStore.allData
    // 将站点站线全部隐藏
    const lineNames = lineDataStore.allData.map(item => item.name)
    lineDataStore.displayLine(lineNames, false)
    // 暂时禁用全局管理，unMount的时候打开
    lineDataStore.disableController(true)
})

onBeforeUnmount(()=>{
    pause()
    // 清除存在的实体
    flyPoint &&  viewer.entities.remove(flyPoint)
    if(lineEnts.length){
        viewer.entities.remove(lineEnts[0])
        lineEnts = []
    }
    // 全局管理恢复，路线展示恢复
    lineDataStore.disableController(false)
    // 将站点站线全部展示
    const lineNames = lineDataStore.allData.map(item => item.name)
    lineDataStore.displayLine(lineNames, true)
     // 相机回到默认视角
    flyToDefaultView(viewer)
})

// 清除所有数据和实体
// const removeCurrentEnts = ()=>{
//     // 清除已经有的数据以及实体
//     removeByCacheData(viewer, dataEnts)
//     dataEnts = {}
// }

// 计算质心函数
let flyPoint
const flyToCentroid =(positions)=>{
    if(positions.length){
        if(flyPoint){
            viewer.entities.remove(flyPoint)
            flyPoint = null
        }
        const dataSource = []
        positions.forEach(item=>{
            const { lng,lat } = item
            dataSource.push([lng,lat])
        })
        // 闭合多边形
        dataSource.push([positions[0].lng,positions[0].lat])
        // 注意：polygon首尾坐标要一致
        const polygonData = polygon([dataSource]);//创建一个 GeoJSON 多边形对象。
        //返回一个包含中心点坐标的 GeoJSON 点对象（{ type: 'Point', coordinates: [经度, 纬度] }）。
        const centroidData = centroid(polygonData);//计算多边形的几何中心点（质心）。
        const { geometry:{ coordinates } } = centroidData
        flyPoint = viewer.entities.add({
            name:'mount',
            position:Cesium.Cartesian3.fromDegrees(coordinates[0],coordinates[1],10000),
            point:{
                pixelSize:0.01
            }
        })
        viewer.flyTo(flyPoint,{
            offset: new Cesium.HeadingPitchRange(Cesium.Math.toRadians(70), Cesium.Math.toRadians(-60), 45000),
            duration:1.5,
        })
    }
}

// 点击线路事件
let dataEnts = {}
let lineEnts = []//重新创建的primitive
const handleItemClick = (item)=>{
    // 如果存在,先清除之前创建的实体
    if(lineEnts.length){
        viewer.entities.remove(lineEnts[0])
        lineEnts = []
    }
    
    const { id,paths,color,name } = item
    const positions = flattenPositions(paths)//将[{lng,lat}]--->[lng,lat,lng,lat]
    // 计算多边形质心，同时跳转
    flyToCentroid(paths)
    pause()//暂停动画
    //removeCurrentEnts()//清除之前的实体和数据
    const target = line_history.find(n=>n.id===id)//通过id找到对应点击线路的历史
    if(target){
        pause()
        currentTime.value = 0
        // 添加isCache的原因
        // 渲染站点站线,不走effectCotroller中的stations缓存,要获取返回值，dataEnts在组件中进行管理
        // 最后一个false，是isCache，是否要使用全局的缓存数据，这个组件，是单独进行实体数据管理的，不能够污染全局数据
        // dataEnts = renderAll(viewer, [item], false)
        const { history } = target;
        max.value = history.length * 10;
        let res = {}
        history.forEach((item,index)=>{
            res[index*10] = {
                style:{
                    color:'#fff',
                    fontSize:10,
                },
                label:item.timePoint,
                message:item.message,
            }
        })
         // 给播放控件赋值，并给路径数据赋值
        marks.value = res;
        resPaths = positions;
        // 截取两个坐标作为动态坐标的初始值
        curPaths = positions.slice(0, 2);
        // 找到路线的实体，并给其坐标重新赋值-----
        // 此处已经修改为primitive创建道路,无法获取positions,所以重新创建primitive---不行结论:primitive不适合用 CallbackProperty 动态修改 positions
        // 因为容易出现类似 “Vertex texture fetch support is required” 的错误。
        // const linePrimitives = dataEnts.lineEnts[0]
        const lineEnt = createEnt(name,color,paths,curPaths)
        // 给播放控件赋值，并给路径数据赋值(给线路实体坐标改为CallbackProperty,后面动态调整,达到线路一直增加的效果)
        lineEnt.polyline.positions = new Cesium.CallbackProperty(() => Cesium.Cartesian3.fromDegreesArray(curPaths), false)
        // 自动开始播放
        play()
    }
}

// 重新创建ent来实现动画
const createEnt = (name,color,paths,curPaths)=>{
  const positionsR = [];
  paths.forEach((path) => {
    positionsR.push(path.lng, path.lat);
  });
  const positionRes = Cesium.Cartesian3.fromDegreesArray(positionsR);
  const lineEnt = viewer.entities.add({
    name,
    polyline: {
      positions:positionRes,
      width: 20,
      //使用cesium默认的泛光线
      material: new Cesium.PolylineGlowMaterialProperty({
        color: new Cesium.Color.fromCssColorString(color),
        glowPower: 0.12,
      }),
    },
  });
  lineEnts.push(lineEnt);
  return lineEnt;
}

// 点击暂停事件
const pause = ()=>{
    isAnimate = false
}

// 播放事件
let myRequestID = null;
const play = ()=>{
    // 播放之前,把上一次的raf给清除
    cancelAnimationFrame(myRequestID)
    const animate = ()=>{
        if(isAnimate){
            currentTime.value += 0.1;
            // 百分比形式的播放进度
            const rate = currentTime.value / max.value;
            let index = Math.ceil(rate * resPaths.length);
            // 我们的坐标两个为一组，不为双数的话，就加一
            if (index % 2 !== 0) {
                index = index + 1;
            }
            // 如果是最后一个坐标，就返回
            if (index >= resPaths.length - 1) {
                // curPaths当前播放的坐标数组
                curPaths = resPaths;
                isAnimate = false
                return;
            }
            curPaths = resPaths.slice(0, index);
            myRequestID=requestAnimationFrame(animate)
        }
    }
    isAnimate = true
    animate()
}

// 重置播放
const replay = () => {
    pause();
    currentTime.value = 0;
    curPaths = resPaths.slice(0, 2);
    play();
}

// 监听当前进度
// 1.找到当前进度在marks当中的下标
// 2.通过下标,找message
watch(currentTime,(val)=>{
    let targetIndex = null
    const markKeys = Object.keys(marks.value).map(n=>Number(n)) // 时间点数组（如 [0, 10, 20, ...]）
    const markValues = Object.values(marks.value)//事件信息数组
    markKeys.forEach((m,index)=>{
        // 判断val是否在值区间
        if(index> val<=m && val> markKeys[index-1]){
            targetIndex = index
        }
        if(val <= m && index === 0){
            targetIndex = index
        }
    })
    if(targetIndex){
        const result = markValues[targetIndex];
        message.value = result.message;
    }else{
        message.value = ''
    }
})
</script>

<style scoped>
#subLine-controller {
    position: absolute;
    bottom: 0;
    left: 32%;
    transform: translateX(-50%);
    width: 7.625vw;
    height: 7.292vw;
    background-color: rgba(0, 0, 0, 0.3);
    border: 1px solid #664a16;
    padding: 4px;
    display: flex;
    flex-direction: column;
}

.box {
    width: 10px;
    height: 10px;
    border-width: 1px;
    border-style: solid;
    background: transparent;
    user-select: all;
    cursor: pointer;
}

.item {
    width: 3.385vw;
    height: 1.042vw;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 0.156vw;
    background-color: rgba(255, 255, 255, 0.2);
    border: 1px solid #885f12;
    color: #fff;
    font-size: 0.521vw;
    pointer-events: all;
    cursor: pointer;
}

.item:hover {
    border: 1px solid #d8961a;
}

.item>span {
    line-height: 0.469vw;
}

.item>input {
    outline: none;
    border: none;
    transition: all 0.3s ease;
}

.item-wrapper {
    display: flex;
    justify-content: space-between;
    align-content: space-around;
    flex-wrap: wrap;
    flex: 1;
}

.active-panel {
    width: 580px;
    height: 170px;
    border: 1px solid #ab7818;
    background-color: rgba(0, 0, 0, 0.3);
    position: absolute;
    left: 37%;
    bottom: 0;
    color: #fff;
    overflow: hidden;
    display: flex;
    flex-direction: column;
}

.active-panel>.header {
    height: 1.563vw;
    padding: 0.208vw;

    margin-bottom: -0.521vw;
    font-family: "等线Bold";
    display: flex;
    align-items: center;
    justify-content: space-between;
}

.active-panel>.header>strong {
    background: rgb(255, 255, 255);
    background-image: linear-gradient(180deg,
            rgba(255, 255, 255, 1) 9%,
            rgba(211, 156, 50, 1) 57%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}

.controler {
    width: 100px;
    display: flex;
    align-items: center;
    justify-content: space-around;
}

.controler>i {
    cursor: pointer;
    pointer-events: all;
    font-size: 20px;
}

.controler>i:hover {
    background: rgb(255, 255, 255);
    background-image: linear-gradient(180deg,
            rgba(255, 255, 255, 1) 9%,
            rgba(211, 156, 50, 1) 57%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}

.active-panel>.header>strong {
    font-weight: normal;
    margin-right: 0.521vw;
}

.active-panel>.header>span {
    font-size: 0.625vw;
}

.content {
    flex: 1;
    padding: 0 30px;
    margin-top: 30px;
}

.message {
    position: absolute;
    bottom: 26px;
    left: 50%;
    transform: translateX(-50%);
    background-color: rgba(0, 0, 0, 0.3);
    color: #fff;
    text-align: center;
}
</style>